1) 事件監聽到底是什麼?
瀏覽器在使用者操作或生命週期發生時,會產生 Event 物件(如 MouseEvent、KeyboardEvent、InputEvent)。
你用 addEventListener(type, handler, options) 登記「有人來就通知我」。
事件物件會帶著發生時的上下文(滑鼠座標、鍵盤鍵值、目標元素等)交給 handler。
button.addEventListener('click', (e) => {
// e 是 Event 物件
});
**2) 事件流程(三階段):捕獲 → 目標 → 冒泡
**
事件從 window 自上而下 捕獲 (capturing) 到目標節點,再自下而上 冒泡 (bubbling) 回 window。
預設 addEventListener('click', handler) 會在冒泡階段觸發。
若要在捕獲階段觸發:addEventListener('click', handler, { capture: true })
window
└─ document
└─ html
└─ body
└─ div.container
└─ button#buy ← 目標 (target)
為什麼重要?因為你可以:
在捕獲階段先攔截/記錄
在冒泡階段做事件代理(下一節)
3) 事件代理(Event Delegation)
把事件綁在父元素一次就好,利用冒泡處理大量子元素,效能與維護性更佳。
list.addEventListener('click', (e) => {
if (e.target.matches('.delete')) {
e.target.closest('li').remove();
}
});
適用情境:動態新增的列表項目、表格操作列、卡片群組按鈕等。
**4) target vs currentTarget
**
e.target:真正被點到的最深層元素(可能是 <span> 裡的圖示)。
e.currentTarget:目前觸發 handler 的元素(你綁監聽在哪個元素就是誰)。
container.addEventListener('click', (e) => {
console.log('target:', e.target); // 可能是內層圖示
console.log('currentTarget:', e.currentTarget); // container
});
5) 阻止預設行為與阻止傳播
a.addEventListener('click', (e) => {
e.preventDefault(); // 不跳轉
});
6) addEventListener 的 options
第三個參數可以是布林或物件,現代寫法用物件:
window.addEventListener('scroll', handle, { passive: true });
button.addEventListener('click', buyOnce, { once: true });